package com.spirit.dcs.idempotent.controller;

import com.spirit.dcs.idempotent.entity.OrderState;
import com.spirit.dcs.idempotent.service.OrderService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author <a href="eric_zheng@lanzuo.com.cn">eric</a>
 * @version 1.0.0
 * Description:
 */
@RestController
public class OrderController {

    @Resource
    private OrderService orderService;

    /**
     * 创建订单（伪代码）
     * 此接口意为分段补偿执行未完成的业务
     * 如果该订单已经完成，那么多次提交不会影响最终结果
     * <p>
     * 流程是不会由页面多次提交完成，订单是不能重复提交的，
     * 下面会演示如何控制，这里业务是执行后推到完成，
     * 也可能业务向前清理，把整个流程置为失败，
     * 这里涉及关键状态判断，
     * 要选取一个状态作为成功或失败的标识，
     * 判断后续操作流程。
     *
     * @param orderState 订单状态
     * @return 提交结果
     */
    @PostMapping("/submitOrder")
    public String submitOrder(OrderState orderState) {
        // 1. 在入库前先查询下订单状态
        OrderState orderState01 = orderService.queryOrder(orderState);
        // 如果没有查询到，则说明是新增的
        if (orderState01 == null) {
            // 执行正常的业务流程
            orderService.createOrder(orderState);
            orderService.localBiz(orderState);
            orderService.paymentBiz(orderState);
        } else {
            switch (orderState01.getState()) {
                case 1:
                    // 状态为1 ，则进行后续操作
                    // 订单创建成功：后推执行本地和支付业务
                    orderService.localBiz(orderState01);
                    orderService.paymentBiz(orderState01);
                    break;
                case 2:
                    // 订单本地业务成功：后推执行支付业务
                    orderService.paymentBiz(orderState01);
                    break;
                default:
                    break;
            }
        }

        return "success";
    }

    /**
     * 在实际情况中，接口如果处理时间过长，用户可能会点击多次提交按钮，导致数据重复。
     * <p>
     * 常见的一个解决方案：在表单提交中隐藏一个token_id参数，
     * 一起提交到接口服务中，数据库存储订单和关联的tokenId，
     * 如果多次提交，直接返回页面提示信息即可。
     *
     * @param orderState
     * @return
     */
    @PostMapping("/repeatSub")
    public String repeatSub(OrderState orderState) {
        boolean flag = orderService.queryToken(orderState);
        if (flag) {
            return "请勿重复提交订单";
        }
        return "success";
    }
}
